package jmcnet.libcommun.communs.time
{
	import mx.controls.HorizontalList;
	
	public class Time
	{
		private var _hh:int=0;
		private var _mm:int=0;
		private var _ss:int=0;
		private var _ms:int=0;
		
		public static const SEPARATOR_TIME:String=":";
		public static const SEPARATOR_MILLISEC:String=".";
		
		public function Time(hh:uint=0, mm:uint=0, ss:uint=0, ms:uint=0) {
			setTime(hh,mm,ss,ms);
		}
		
		public function setCurrentTime():void {
			setDate(new Date());
		}
		
		public function setDate(date:Date):void {
			setTime(date.hours,date.minutes,date.seconds, date.milliseconds);
		}
		
		public function setTime(hh:uint, mm:uint=0, ss:uint=0, ms:uint=0):void {
			_hh = hh;
			_mm = mm;
			_ss = ss;
			_ms = ms;
			
			normalize();
		}
		
		/**
		 * Renvoie true si un débordement de capacité a eu lieu
		 */
		public function normalize():Boolean {
			if (_ms < 0) {
				_ms += 1000;
				_ss -= 1;
			}
			if (_ss < 0) {
				_ss += 60;
				_mm -= 1;
			}
			if (_mm < 0) {
				_mm += 60;
				_hh -= 1;
			}

			if (_ms > 1000) {
				_ss += _ms / 1000;
				_ms = _ms % 1000;
			}
			
			if (_ss > 60) {
				_mm += _ss / 60;
				_ss = _ss % 60;
			}
			
			if (_mm > 60) {
				_hh += _mm / 60;
				_mm = _mm % 60;
			}
			
			if (_hh > 24 || _hh < 0) {
				_hh = (_hh + 24) % 24;
				return true;
			}
			else return false;			
		}
		
		public function timeToString(hb:Boolean=true, mb:Boolean=true, sb:Boolean=true, msb:Boolean=true):String {
			var res:String="";
			var hstr:String = ""+(_hh < 10 ? "0":"")+_hh;
			var mstr:String = ""+(_mm < 10 ? "0":"")+_mm;
			var sstr:String = ""+(_ss < 10 ? "0":"")+_ss;
			var msstr:String = ""+(_ms < 10 ? "00": (_ms<100 ? "0":""))+_ms;
			
			if (hb) res += hstr;
			if (hb && mb) res += ":";
			if (mb) res += mstr;
			if (res.length > 0 && sb) res += ":";
			if (sb) res += sstr;
			if (res.length > 0 && msb) res += "."; 
			if (msb) res += msstr;
			
			return res;
		}
		
		public static function stringToTime(str:String, hb:Boolean=true, mb:Boolean=true, sb:Boolean=true, msb:Boolean=true):Time {
			if (str == null || str.length <= 0) return null;
			var res:Time = new Time();
			var delim:RegExp = /[:.]/;
			var h:Array = str.split(delim);
			var i:int=0;
			if (hb) {
				if (h.length <= i) throw new Error("Illegal Time format. Hour expected. Get : "+str);
				res.hour = h[i++];
			}
			
			if (mb) {
				if (h.length <= i) throw new Error("Illegal Time format. Minute expected. Get : "+str);
				res.minute = h[i++];
			}
			
			if (sb) {
				if (h.length <= i) throw new Error("Illegal Time format. Second expected. Get : "+str);
				res.second = h[i++];
			}
			
			if (msb) {
				if (h.length <= i) throw new Error("Illegal Time format. Millisecond expected. Get : "+str);
				res.millisecond = h[i++];
			}
			
			return res;			
		}
		
		public function addTime(t:Time):Boolean {
			_hh += t.hour;
			_mm += t.minute;
			_ss += t.second;
			_ms += t.millisecond;
			return normalize();
		}
		
		public function subTime(t:Time):Boolean {
			_hh -= t.hour;
			_mm -= t.minute;
			_ss -= t.second;
			_ms -= t.millisecond;
			return normalize();
		}
		
		public function get hour():uint { return _hh;};
		public function get minute():uint { return _mm;};
		public function get second():uint { return _ss;};
		public function get millisecond():uint { return _ms;};
		
		public function set hour(hh:uint):void { _hh = hh; normalize();};
		public function set minute(mm:uint):void  { _mm = mm; normalize();};
		public function set second(ss:uint):void { _ss = ss; normalize();};
		public function set millisecond(ms:uint):void { _ms = ms; normalize();};
		
		public function toString():String {
			return timeToString(true, true, true, true);
		}
	}
}